<?php

namespace App\Services;

use App\Models\Product;
use App\Models\ProductVariant;
use Illuminate\Support\Facades\DB;

class StockService
{
    /**
     * 检查商品库存是否充足
     *
     * @param int $productId
     * @param int|null $variantId
     * @param int $quantity
     * @return array ['available' => bool, 'stock' => int, 'message' => string]
     */
    public function checkStock(int $productId, ?int $variantId, int $quantity): array
    {
        if ($variantId) {
            $variant = ProductVariant::find($variantId);
            
            if (!$variant) {
                return [
                    'available' => false,
                    'stock' => 0,
                    'message' => '商品规格不存在'
                ];
            }

            if (!$variant->is_active) {
                return [
                    'available' => false,
                    'stock' => 0,
                    'message' => '该规格已下架'
                ];
            }

            $stock = $variant->stock_quantity;
        } else {
            $product = Product::find($productId);
            
            if (!$product) {
                return [
                    'available' => false,
                    'stock' => 0,
                    'message' => '商品不存在'
                ];
            }

            if (!$product->is_active) {
                return [
                    'available' => false,
                    'stock' => 0,
                    'message' => '商品已下架'
                ];
            }

            $stock = $product->stock_quantity;
        }

        if ($stock < $quantity) {
            return [
                'available' => false,
                'stock' => $stock,
                'message' => "库存不足，当前库存：{$stock}"
            ];
        }

        return [
            'available' => true,
            'stock' => $stock,
            'message' => '库存充足'
        ];
    }

    /**
     * 批量检查购物车商品库存
     *
     * @param array $items [['product_id' => int, 'variant_id' => int|null, 'quantity' => int], ...]
     * @return array ['success' => bool, 'errors' => array]
     */
    public function checkCartStock(array $items): array
    {
        $errors = [];

        foreach ($items as $item) {
            $check = $this->checkStock(
                $item['product_id'],
                $item['variant_id'] ?? null,
                $item['quantity']
            );

            if (!$check['available']) {
                $errors[] = [
                    'product_id' => $item['product_id'],
                    'variant_id' => $item['variant_id'] ?? null,
                    'message' => $check['message']
                ];
            }
        }

        return [
            'success' => empty($errors),
            'errors' => $errors
        ];
    }

    /**
     * 扣减库存
     *
     * @param int $productId
     * @param int|null $variantId
     * @param int $quantity
     * @return bool
     * @throws \Exception
     */
    public function deductStock(int $productId, ?int $variantId, int $quantity): bool
    {
        try {
            DB::beginTransaction();

            if ($variantId) {
                // 多规格商品，扣减变体库存
                $variant = ProductVariant::lockForUpdate()->find($variantId);
                
                if (!$variant || $variant->stock_quantity < $quantity) {
                    throw new \Exception('库存不足');
                }

                $variant->decrement('stock_quantity', $quantity);

                // 同时更新产品总库存
                $product = Product::lockForUpdate()->find($productId);
                if ($product) {
                    $product->decrement('stock_quantity', $quantity);
                }
            } else {
                // 单规格商品，扣减产品库存
                $product = Product::lockForUpdate()->find($productId);
                
                if (!$product || $product->stock_quantity < $quantity) {
                    throw new \Exception('库存不足');
                }

                $product->decrement('stock_quantity', $quantity);
            }

            DB::commit();
            return true;

        } catch (\Exception $e) {
            DB::rollBack();
            throw $e;
        }
    }

    /**
     * 恢复库存（订单取消时）
     *
     * @param int $productId
     * @param int|null $variantId
     * @param int $quantity
     * @return bool
     */
    public function restoreStock(int $productId, ?int $variantId, int $quantity): bool
    {
        try {
            DB::beginTransaction();

            if ($variantId) {
                // 多规格商品，恢复变体库存
                $variant = ProductVariant::find($variantId);
                if ($variant) {
                    $variant->increment('stock_quantity', $quantity);
                }

                // 同时更新产品总库存
                $product = Product::find($productId);
                if ($product) {
                    $product->increment('stock_quantity', $quantity);
                }
            } else {
                // 单规格商品，恢复产品库存
                $product = Product::find($productId);
                if ($product) {
                    $product->increment('stock_quantity', $quantity);
                }
            }

            DB::commit();
            return true;

        } catch (\Exception $e) {
            DB::rollBack();
            return false;
        }
    }

    /**
     * 批量扣减库存
     *
     * @param array $items [['product_id' => int, 'variant_id' => int|null, 'quantity' => int], ...]
     * @return bool
     * @throws \Exception
     */
    public function batchDeductStock(array $items): bool
    {
        try {
            DB::beginTransaction();

            foreach ($items as $item) {
                $this->deductStockWithoutTransaction(
                    $item['product_id'],
                    $item['variant_id'] ?? null,
                    $item['quantity']
                );
            }

            DB::commit();
            return true;

        } catch (\Exception $e) {
            DB::rollBack();
            throw $e;
        }
    }

    /**
     * 扣减库存（不包含事务，用于批量操作）
     *
     * @param int $productId
     * @param int|null $variantId
     * @param int $quantity
     * @return bool
     * @throws \Exception
     */
    private function deductStockWithoutTransaction(int $productId, ?int $variantId, int $quantity): bool
    {
        if ($variantId) {
            // 多规格商品，扣减变体库存
            $variant = ProductVariant::lockForUpdate()->find($variantId);
            
            if (!$variant || $variant->stock_quantity < $quantity) {
                throw new \Exception('库存不足');
            }

            $variant->decrement('stock_quantity', $quantity);

            // 同时更新产品总库存
            $product = Product::lockForUpdate()->find($productId);
            if ($product) {
                $product->decrement('stock_quantity', $quantity);
            }
        } else {
            // 单规格商品，扣减产品库存
            $product = Product::lockForUpdate()->find($productId);
            
            if (!$product || $product->stock_quantity < $quantity) {
                throw new \Exception('库存不足');
            }

            $product->decrement('stock_quantity', $quantity);
        }

        return true;
    }

    /**
     * 批量恢复库存
     *
     * @param array $items [['product_id' => int, 'variant_id' => int|null, 'quantity' => int], ...]
     * @return bool
     */
    public function batchRestoreStock(array $items): bool
    {
        try {
            DB::beginTransaction();

            foreach ($items as $item) {
                $this->restoreStock(
                    $item['product_id'],
                    $item['variant_id'] ?? null,
                    $item['quantity']
                );
            }

            DB::commit();
            return true;

        } catch (\Exception $e) {
            DB::rollBack();
            return false;
        }
    }
}

